package vg.modules.navigator;

import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;

import vg.modules.navigator.components.GraphComparisonMenuItem;
import vg.modules.navigator.components.GraphTreeComparisonMenuItem;
import vg.modules.navigator.components.IMenuItem;
import vg.modules.navigator.components.OpenSubGraphMenuItem;
import vg.modules.navigator.components.OpenVerticesMenuItem;
import vg.modules.navigator.components.SelectionTabMenuItem;
import vg.services.plugin_manager.realization.PluginParameter;

/**
 * This class manages of actions of tree. 
 * @author tzolotuhin
 */
public class NodeManager {
	private final JTree tree;
	private final JPopupMenu popup;
	private final PluginParameter parameter;
	//Actions
	private final List<IMenuItem>menuItems;
	private final OpenVerticesMenuItem openVerticesMenuItem;
	private final SelectionTabMenuItem selectionTabMenuItem;
	private final OpenSubGraphMenuItem openSubGraphMenuItem;
	private final GraphTreeComparisonMenuItem graphModelComparisonMenuItem;
	private final GraphComparisonMenuItem graphComparisonMenuItem;
	/**
	 * Constructor.
	 * @param tree - tree of graph nodes.
	 * @param parameter - plugin parameter.
	 */
	public NodeManager(final JTree tree, final PluginParameter parameter) {
		// initialize
		this.tree = tree;
		this.parameter = parameter;
		this.popup = new JPopupMenu();
		this.menuItems = new ArrayList<IMenuItem>(10);
		this.openVerticesMenuItem = new OpenVerticesMenuItem(tree, this.parameter.graphDataBase, this.parameter.userInterfaceManager);
		this.selectionTabMenuItem = new SelectionTabMenuItem(tree, this.parameter.userInterfaceManager);
		this.openSubGraphMenuItem = new OpenSubGraphMenuItem(tree, this.parameter.graphDataBase, this.parameter.userInterfaceManager);
		this.graphModelComparisonMenuItem = new GraphTreeComparisonMenuItem(tree, this.parameter.graphDataBase, this.parameter.userInterfaceManager);
		this.graphComparisonMenuItem = new GraphComparisonMenuItem(tree, this.parameter.graphDataBase, this.parameter.userInterfaceManager);
		// check input parameter
		if(tree == null) return;
		// create items
		this.menuItems.add(this.openVerticesMenuItem);
		this.menuItems.add(this.openSubGraphMenuItem);
		this.menuItems.add(this.selectionTabMenuItem);
		this.menuItems.add(this.graphModelComparisonMenuItem);
		this.menuItems.add(this.graphComparisonMenuItem);
		// add mouse listener to jTree
		this.tree.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				mouseReleased(e);
				if(e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() >= 2){
					doSomething();
				}
			}
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					// focus for right mouse click
		            TreePath treePath = tree.getClosestPathForLocation(e.getX(), e.getY());
		            if (!tree.isPathSelected(treePath)) {
		                tree.setSelectionPath(treePath);
		            }
		            // build popMenu
					buildPopupMenu(e.getComponent(), e.getX(), e.getY());
				}
			}
		});
		// add key listener to jTree
		this.tree.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER) {
					doSomething();
				}
			}
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER) {
					if(openSubGraphMenuItem.isVisible()) {
						TreePath path = tree.getSelectionPath();
						if(path != null) {
							if(tree.isCollapsed(path)) {
								tree.expandPath(path);
							} else {
								tree.collapsePath(path);
							}
						}
					}
				}
			}
		});
	}
	private synchronized void buildPopupMenu(Component invoker, int x, int y) {
		if(this.tree == null) return;
		
		this.popup.removeAll();
		for(IMenuItem buf : this.menuItems) {
			if(buf.isVisible()) {
				this.popup.add(buf.getMenuItem());
			}
		}
		if(this.popup.getComponentCount() > 0) {
			this.popup.show(invoker, x, y);
		}
	}
	public synchronized void updateTheme() {
		SwingUtilities.updateComponentTreeUI(popup);
		for(IMenuItem buf : this.menuItems) {
			buf.updateTheme();
		}
	}
	/**
	 * This method does default action.
	 */
	private synchronized void doSomething() {
		if(this.openVerticesMenuItem.isVisible() && !this.openSubGraphMenuItem.isVisible()) {
			this.openVerticesMenuItem.getMenuItem().doClick();
		}
		if(this.selectionTabMenuItem.isVisible()) {
			this.selectionTabMenuItem.getMenuItem().doClick();
		}
	}
}
